"""
认证控制器
提供用户注册、登录、Token刷新等功能
"""
from flask import Blueprint, request, jsonify, g
from src.models.user import User
from src.database import db
from src.utils.jwt_utils import generate_token, verify_token, require_auth
from src.utils.security import hash_password, check_password, validate_json_input
from src.utils.rate_limit import rate_limit
from datetime import datetime

auth_bp = Blueprint('auth', __name__)

@auth_bp.route('/register', methods=['POST'])
@rate_limit(limit=5, window=300, per='ip')  # 5分钟内最多5次注册
@validate_json_input({
    'username': {'required': True, 'type': str, 'min_length': 3, 'max_length': 20},
    'password': {'required': True, 'type': str, 'min_length': 6, 'max_length': 100},
    'email': {'required': False, 'type': str},
    'student_id': {'required': False, 'type': str}
})
def register():
    """用户注册"""
    try:
        data = request.validated_data
        username = data.get('username')
        password = data.get('password')
        email = data.get('email')
        student_id = data.get('student_id')
        
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            return jsonify({
                'status': 'error',
                'message': '用户名已存在'
            }), 400
        
        # 检查邮箱是否已存在
        if email and User.query.filter_by(email=email).first():
            return jsonify({
                'status': 'error',
                'message': '邮箱已被注册'
            }), 400
        
        # 检查学号是否已存在
        if student_id and User.query.filter_by(student_id=student_id).first():
            return jsonify({
                'status': 'error',
                'message': '学号已被注册'
            }), 400
        
        # 创建新用户
        user = User(
            username=username,
            email=email,
            password_hash=hash_password(password),
            student_id=student_id,
            role='student'
        )
        
        db.session.add(user)
        db.session.commit()
        
        return jsonify({
            'status': 'success',
            'message': '注册成功',
            'data': {
                'user_id': user.id,
                'username': user.username
            }
        }), 201
        
    except Exception as e:
        db.session.rollback()
        return jsonify({
            'status': 'error',
            'message': f'注册失败: {str(e)}'
        }), 500

@auth_bp.route('/login', methods=['POST'])
@rate_limit(limit=10, window=300, per='ip')  # 5分钟内最多10次登录尝试
@validate_json_input({
    'username': {'required': True, 'type': str},
    'password': {'required': True, 'type': str}
})
def login():
    """用户登录"""
    try:
        data = request.validated_data
        username = data.get('username')
        password = data.get('password')
        
        # 查找用户（支持用户名、邮箱或学号登录）
        user = User.query.filter(
            (User.username == username) |
            (User.email == username) |
            (User.student_id == username)
        ).first()
        
        if not user:
            return jsonify({
                'status': 'error',
                'message': '用户名或密码错误'
            }), 401
        
        if not user.is_active:
            return jsonify({
                'status': 'error',
                'message': '账户已被禁用'
            }), 403
        
        # 验证密码
        if not check_password(password, user.password_hash):
            return jsonify({
                'status': 'error',
                'message': '用户名或密码错误'
            }), 401
        
        # 更新最后登录时间
        user.last_login = datetime.utcnow()
        db.session.commit()
        
        # 生成Token
        tokens = generate_token(user.id, user.username, user.role)
        
        return jsonify({
            'status': 'success',
            'message': '登录成功',
            'data': {
                'user': user.to_dict(),
                **tokens
            }
        }), 200
        
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': f'登录失败: {str(e)}'
        }), 500

@auth_bp.route('/refresh', methods=['POST'])
@validate_json_input({
    'refresh_token': {'required': True, 'type': str}
})
def refresh():
    """刷新Token"""
    try:
        data = request.validated_data
        refresh_token = data.get('refresh_token')
        
        # 验证Refresh Token
        payload = verify_token(refresh_token)
        if not payload or payload.get('type') != 'refresh':
            return jsonify({
                'status': 'error',
                'message': '无效的刷新令牌'
            }), 401
        
        # 获取用户信息
        user = User.query.get(payload.get('user_id'))
        if not user or not user.is_active:
            return jsonify({
                'status': 'error',
                'message': '用户不存在或已被禁用'
            }), 401
        
        # 生成新的Token
        tokens = generate_token(user.id, user.username, user.role)
        
        return jsonify({
            'status': 'success',
            'message': 'Token刷新成功',
            'data': tokens
        }), 200
        
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': f'Token刷新失败: {str(e)}'
        }), 500

@auth_bp.route('/me', methods=['GET'])
@require_auth
def get_current_user_info():
    """获取当前用户信息"""
    try:
        user = User.query.get(g.current_user['user_id'])
        if not user:
            return jsonify({
                'status': 'error',
                'message': '用户不存在'
            }), 404
        
        return jsonify({
            'status': 'success',
            'data': user.to_dict()
        }), 200
        
    except Exception as e:
        return jsonify({
            'status': 'error',
            'message': f'获取用户信息失败: {str(e)}'
        }), 500

@auth_bp.route('/logout', methods=['POST'])
@require_auth
def logout():
    """用户登出（前端删除Token即可，这里主要是记录日志）"""
    return jsonify({
        'status': 'success',
        'message': '登出成功'
    }), 200

